package com.kwan.xframe.mvvm.view.activity;

import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.ContentObserver;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.provider.Settings;
import android.util.SparseArray;
import android.view.View;
import android.view.ViewStub;
import android.view.ViewTreeObserver;
import android.view.Window;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.LinearLayout;

import com.blankj.utilcode.util.ActivityUtils;
import com.blankj.utilcode.util.BarUtils;
import com.blankj.utilcode.util.ScreenUtils;
import com.blankj.utilcode.util.ToastUtils;
import com.kwan.xframe.immersionbar.ImmersionBar;
import com.kwan.xframe.immersionbar.OSUtils;
import com.kwan.xframe.R;
import com.kwan.xframe.common.bean.TitleEntity;
import com.kwan.xframe.common.image.ImageLoader;
import com.kwan.xframe.common.image.glide.GlideLoader;
import com.kwan.xframe.databinding.LayoutBaseBinding;
import com.kwan.xframe.mvp.presenter.IBaseView;
import com.kwan.xframe.mvvm.binding.DataBindingConfig;
import com.kwan.xframe.mvvm.scope.ViewModelScope;
import com.kwan.xframe.util.PermissionUtil;
import com.kwan.xframe.view_model.BaseViewModel;

import com.lxj.xpopup.XPopup;
import com.lxj.xpopup.impl.LoadingPopupView;
import com.orhanobut.logger.Logger;
import com.trello.rxlifecycle4.components.support.RxAppCompatActivity;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.databinding.DataBindingUtil;
import androidx.databinding.ViewDataBinding;
import androidx.lifecycle.ViewModel;

import me.jessyan.autosize.AutoSize;
import timber.log.Timber;


/**
 * 基类Activity 项目所有Activity都应该继承此类
 * Created by Mr.Kwan on 2017-7-19.
 */

public abstract class BaseActivity<V extends ViewDataBinding> extends RxAppCompatActivity
		implements View.OnClickListener,
		IBaseView, PermissionUtil.PermissionListener
		//CustomAdapt,
{

	protected String TAG;
	protected View mRootContentView, mViewBar;
	protected LinearLayout cl_root;
	private boolean mLastVisible;
	protected LoadingPopupView mLoadingDialog;
	protected PermissionUtil mPermissionUtil;
	protected ImageLoader mImageLoader;
	protected boolean isResume = false;
	LayoutBaseBinding mBaseBinding;

	protected Activity activity;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		Timber.e("onCreate "+this);
		activity = this;
		beForeSetContentView();
		mBaseBinding = DataBindingUtil.setContentView(this, R.layout.layout_base);
		mBaseBinding.setLifecycleOwner(this);
		mBaseBinding.setTitle(getTitleEntity());
		initBaseViews();
		initTitleBar();
		init();
		//初始化沉浸式状态栏
		initBar();
		initViews();
		initViewSetting();
		initData();
		addOnSoftKeyBoardVisibleListener();

	}


	// ---------  ViewModel --------------

	private final ViewModelScope mViewModelScope = new ViewModelScope();

	protected <T extends ViewModel> T getActivityScopeViewModel(@NonNull Class<T> modelClass) {
		return mViewModelScope.getActivityScopeViewModel(this, modelClass);
	}

	protected <T extends ViewModel> T getApplicationScopeViewModel(@NonNull Class<T> modelClass) {
		return mViewModelScope.getApplicationScopeViewModel(modelClass);
	}

	@Override
	protected void onPostResume() {
		super.onPostResume();
	}

	@Override
	protected void onResumeFragments() {
		super.onResumeFragments();
	}


	@Override
	protected void onRestart() {
		super.onRestart();
		Timber.e("onRestart "+this);
	}

	@Override
	protected void onStart() {
		super.onStart();
		Timber.e("onStart "+this);
	}

	@Override
	protected void onResume() {
		super.onResume();
		Timber.e("onResume "+this);
		isResume = true;
	}

	@Override
	protected void onPause() {
		super.onPause();
		Timber.e("onPause "+this);
		isResume = false;
	}

	@Override
	protected void onStop() {
		super.onStop();
		Timber.e("onStop "+this);
	}

	@Override
	protected void onDestroy() {
		super.onDestroy();
		Timber.e("onDestroy "+this);
	}

	protected void beForeSetContentView() {
		if (isFullScreen()) {
			this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
			this.supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
			BarUtils.setStatusBarColor(this, Color.TRANSPARENT);
			BarUtils.setStatusBarLightMode(this, true);
			ScreenUtils.setFullScreen(this);
			BarUtils.setNavBarVisibility(this, false);
		}
	}

	public boolean isLandScreen() {
		return false;
	}

	protected V mBinding;

	private void initBaseViews() {

		DataBindingConfig dataBindingConfig = getDataBindingConfig();
		cl_root = findViewById(R.id.cl_root);
		mViewBar = findViewById(R.id.view_bar);

		ViewStub stubMainContent = findViewById(R.id.view_stub_content);
		if (stubMainContent != null) {
			stubMainContent.setLayoutResource(dataBindingConfig.getLayout());
			mRootContentView = stubMainContent.inflate();
		}

		if (getBackGroundBitmap() != null) {
			cl_root.setBackground(new BitmapDrawable(getResources(), getBackGroundBitmap()));
		} else if (getBackGroundRes() != 0) {
			cl_root.setBackgroundResource(getBackGroundRes());
		} else {
			cl_root.setBackgroundColor(getBackGroundColor());
		}

		//StatusBarCompat.setStatusBarColor(this, Color.parseColor("#000000"));


		if (mRootContentView != null) {
			mBinding = DataBindingUtil.bind(mRootContentView);
			assert mBinding != null;
			mBinding.setLifecycleOwner(this);

			if (dataBindingConfig.getStateViewModel() != null) {
				getLifecycle().addObserver(dataBindingConfig.getStateViewModel());
				if (dataBindingConfig.getVmVariableId() != -1) {
					mBinding.setVariable(dataBindingConfig.getVmVariableId(), dataBindingConfig.getStateViewModel());
				}
			}

			SparseArray<BaseViewModel> bindingParams = dataBindingConfig.getBindingParams();
			if (bindingParams != null) {
				for (int i = 0, length = bindingParams.size(); i < length; i++) {
					if (bindingParams.valueAt(i) != null) {
						//让ViewModel拥有View的生命周期感应
						getLifecycle().addObserver(bindingParams.valueAt(i));
						if (bindingParams.keyAt(i) != -1)
							mBinding.setVariable(bindingParams.keyAt(i), bindingParams.valueAt(i));
					}
				}
			}
		}
	}


	private void initTitleBar() {
		//TitleBar 左边
		ViewStub stubTitleBarLeft = findViewById(R.id.view_stub_title_left);
		if (stubTitleBarLeft != null
				&& getTitleEntity() != null
				&& getTitleEntity().getLeftLayoutId() != 0) {


			stubTitleBarLeft.inflate();
		}
	}


	@Override
	public void onClick(View v) {

	}

	/**
	 * 设置 Activity 是否为全屏
	 *
	 * @return 是否为全屏
	 */

	public boolean isFullScreen() {
		return false;
	}

	private void init() {

		TAG = this.getClass().getSimpleName();
		//初始化图片工具
		mImageLoader = new GlideLoader();
		mPermissionUtil = new PermissionUtil();
		mPermissionUtil.setPermissionListener(this);
		//软键盘工具
		XPopup.Builder mLoadingBuilder = new XPopup.Builder(this);
		mLoadingDialog = mLoadingBuilder.asLoading("", R.layout.common_loading_layout, LoadingPopupView.Style.Spinner);
	}


	/*
	 * 是否按照宽度进行等比例适配 (为了保证在高宽比不同的屏幕上也能正常适配, 所以只能在宽度和高度之中选择一个作为基准进行适配)
	 *
	 * //@return {@code true} 为按照宽度进行适配, {@code false} 为按照高度进行适配
	 *
	 *   // @Override
	 *  //  public boolean isBaseOnWidth() {
	 * //	return true;
	 *   // }
	 *
	 *
	 */


	/*
	 * 这里使用 iPhone 的设计图, iPhone 的设计图尺寸为 750px * 1334px, 因为这个页面使用副单位进行布局
	 * 所以可以直接以像素作为单位返回设计图的尺寸
	 * <p>
	 * 返回设计图上的设计尺寸
	 * {#getSizeInDp} 须配合 {#isBaseOnWidth()} 使用, 规则如下:
	 * 如果 { #isBaseOnWidth()} 返回 { true}, { #getSizeInDp} 则应该返回设计图的总宽度
	 * 如果 { #isBaseOnWidth()} 返回 { false}, { #getSizeInDp} 则应该返回设计图的总高度
	 * 如果您不需要自定义设计图上的设计尺寸, 想继续使用在 AndroidManifest 中填写的设计图尺寸, { #getSizeInDp} 则返回 {@code 0}
	 *
	 *  设计图上的设计尺寸
	 * //	@Override
	 * //	public float getSizeInDp() {
	 * //		return 0;
	 * //	}
	 */

	@Override
	public void toastMsg(String msg) {
		AutoSize.cancelAdapt(this);
		ToastUtils.showShort(msg);
	}

	@Override
	public void onNoNetWork() {
		toastMsg(getString(R.string.base_activity_toast_no_network));
	}

	@Override
	public void onReConnect() {

	}

	@Override
	public void onBackPressed() {
		ActivityUtils.finishActivity(this);
		//super.onBackPressed();
	}

	/**
	 * 【强制】Activity 间通过隐式 Intent 的跳转，在发出 Intent 之前必须通过
	 * resolveActivity检查，避免找不到合适的调用组件，造成 ActivityNotFoundException 的异常。
	 *
	 * @param url      url
	 * @param mimeType mimeType
	 */
	public void viewUrl(String url, String mimeType) {
		Intent intent = new Intent(Intent.ACTION_VIEW);
		intent.setDataAndType(Uri.parse(url), mimeType);
		if (getPackageManager().resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY) != null) {
			startActivity(intent);
		} else {
			// 找不到指定的 Activity
			toastMsg(getString(R.string.base_activity_toast_not_find_activity));
		}
	}

	public void Log(String s) {
		Logger.t(TAG).e(s);
	}


	/**
	 * 隐藏虚拟按键，并且全屏
	 */
	protected void hideBottomUIMenu() {
		//隐藏虚拟按键，并且全屏
		if (Build.VERSION.SDK_INT > 11 && Build.VERSION.SDK_INT < 19) { // lower api
			View v = this.getWindow().getDecorView();
			v.setSystemUiVisibility(View.GONE);
		} else if (Build.VERSION.SDK_INT >= 19) {
			//for new api versions.
			Timber.e("导航栏");
			View decorView = getWindow().getDecorView();
			int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | View.SYSTEM_UI_FLAG_FULLSCREEN;
			decorView.setSystemUiVisibility(uiOptions);
		}
	}


	protected void onSoftKeyBoardVisible(boolean visible) {
		//Log("onSoftKeyBoardVisible::" + visible);
	}


	/**
	 * 监听软键盘状态
	 */
	private void addOnSoftKeyBoardVisibleListener() {
		final View decorView = getWindow().getDecorView();
		decorView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
			@Override
			public void onGlobalLayout() {
				Rect rect = new Rect();
				decorView.getWindowVisibleDisplayFrame(rect);
				int displayHeight = rect.bottom - rect.top;
				int height = decorView.getHeight();
				boolean visible = (double) displayHeight / height < 0.8;
				if (visible != mLastVisible) {
					onSoftKeyBoardVisible(visible);
				}
				mLastVisible = visible;
			}
		});
	}

	/**
	 * 设置背景色
	 *
	 * @return 背景色
	 */

	protected int getBackGroundColor() {
		return Color.parseColor("#F9F9F9");
	}

	/**
	 * 设置背景图片
	 *
	 * @return 背景图片Bitmap
	 */
	protected Bitmap getBackGroundBitmap() {
		return null;
	}

	protected int getBackGroundRes() {
		return 0;
	}

	public Object getIntentData(String key) {
		if (getIntent().getExtras() != null) {
			return getIntent().getExtras().get(key);
		} else {
			return null;
		}
	}

	@Override
	public void dismissProgress() {
		mLoadingDialog.dismiss();
	}

	public void showProgress(String str) {
		showProgress(str, true);
	}


	public void showProgress(String str, boolean cancelable) {

		if (mLoadingDialog != null) {
			if (mLoadingDialog.popupInfo != null) {
				mLoadingDialog.popupInfo.isDismissOnTouchOutside = cancelable;
				mLoadingDialog.popupInfo.isDismissOnBackPressed = cancelable;
			}
			Timber.e("showProgress....");
			mLoadingDialog.setTitle(str);
			mLoadingDialog.show();
		} else {
			Timber.e("showProgress null");
		}
	}

	@Override
	public BaseActivity<V> getBaseActivity() {
		return this;
	}

	//	1、方法一(如果输入法在窗口上已经显示，则隐藏，反之则显示)
//[java] view plain copy print?
//	InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
//imm.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);
//
//2、方法二（view为接受软键盘输入的视图，SHOW_FORCED表示强制显示）
//			[java] view plain copy print?
//	InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
//imm.showSoftInput(view,InputMethodManager.SHOW_FORCED);
//[java] view plain copy print?
//			imm.hideSoftInputFromWindow(view.getWindowToken(), 0); //强制隐藏键盘
//
//3、调用隐藏系统默认的输入法
//[java] view plain copy print?
//			((InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(WidgetSearchActivity.this.getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);  (WidgetSearchActivity是当前的Activity)
//
//			4、获取输入法打开的状态
//[java] view plain copy print?
//	InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
//	boolean isOpen=imm.isActive();//isOpen若返回true，则表示输入法打开


	protected void toggleSoftInput() {
		InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
		if (imm != null) {
			imm.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);
		}
	}

	protected abstract DataBindingConfig getDataBindingConfig();

	protected abstract void initViews();

	protected abstract void initViewSetting();

	protected abstract void initData();

	protected abstract TitleEntity getTitleEntity();


	//------------------- 权限相关-------------------------

	@Override
	public void onGranted(String permission) {

	}

	@Override
	public void onShouldShowRequestPermissionRationale(String permission) {
		showRationaleDialog(getResources().getString(R.string.app_name) + "需要请求相关权限", permission);
	}

	@Override
	public void onDenied(String permission) {

	}

	private void showRationaleDialog(String message, final String permission) {
		new AlertDialog.Builder(this).setPositiveButton("请求", new DialogInterface.OnClickListener() {
			@Override
			public void onClick(@NonNull DialogInterface dialog, int which) {
				//mPermissionUtil.requestPermissions(permission);
				dialog.cancel();
			}
		}).setNegativeButton("取消", new DialogInterface.OnClickListener() {
			@Override
			public void onClick(@NonNull DialogInterface dialog, int which) {
				dialog.cancel();
			}
		}).setCancelable(false).setMessage(message).show();
	}

	private void initBar() {
		if (isImmersionBarEnabled()&&!isFullScreen()) {
			initImmersionBar();
		}
		if (OSUtils.isEMUI3_1()) {
			//第一种
			getContentResolver().registerContentObserver(Settings.System.getUriFor(NAVIGATIONBAR_IS_MIN), true, mNavigationStatusObserver);
			//第二种,禁止对导航栏的设置
			//mImmersionBar.navigationBarEnable(false).init();
		}
	}


	public ImmersionBar mImmersionBar;
	private static final String NAVIGATIONBAR_IS_MIN = "navigationbar_is_min";

	/**
	 * 是否可以使用沉浸式
	 * Is immersion bar enabled boolean.
	 *
	 * @return the boolean
	 */
	protected boolean isImmersionBarEnabled() {
		return true;
	}

	protected void initImmersionBar() {
		//在BaseActivity里初始化
		ImmersionBar.with(this)
				.statusBarView(R.id.view_bar)
				.init();
//		ImmersionBar.with(this)
//				.transparentStatusBar()  //透明状态栏，不写默认透明色
//				.transparentNavigationBar()  //透明导航栏，不写默认黑色(设置此方法，fullScreen()方法自动为true)
//				.transparentBar()             //透明状态栏和导航栏，不写默认状态栏为透明色，导航栏为黑色（设置此方法，fullScreen()方法自动为true）
//				.statusBarColor(R.color.colorPrimary)     //状态栏颜色，不写默认透明色
//				.navigationBarColor(R.color.colorPrimary) //导航栏颜色，不写默认黑色
//				.barColor(R.color.colorPrimary)  //同时自定义状态栏和导航栏颜色，不写默认状态栏为透明色，导航栏为黑色
//				.statusBarAlpha(0.3f)  //状态栏透明度，不写默认0.0f
//				.navigationBarAlpha(0.4f)  //导航栏透明度，不写默认0.0F
//				.barAlpha(0.3f)  //状态栏和导航栏透明度，不写默认0.0f
//				.statusBarDarkFont(true)   //状态栏字体是深色，不写默认为亮色
//				.navigationBarDarkIcon(true) //导航栏图标是深色，不写默认为亮色
//				.autoDarkModeEnable(true) //自动状态栏字体和导航栏图标变色，必须指定状态栏颜色和导航栏颜色才可以自动变色哦
//				.autoStatusBarDarkModeEnable(true,0.2f) //自动状态栏字体变色，必须指定状态栏颜色才可以自动变色哦
//				.autoNavigationBarDarkModeEnable(true,0.2f) //自动导航栏图标变色，必须指定导航栏颜色才可以自动变色哦
//				.flymeOSStatusBarFontColor(R.color.btn3)  //修改flyme OS状态栏字体颜色
//				.fullScreen(true)      //有导航栏的情况下，activity全屏显示，也就是activity最下面被导航栏覆盖，不写默认非全屏
//				.hideBar(BarHide.FLAG_HIDE_BAR)  //隐藏状态栏或导航栏或两者，不写默认不隐藏
//				.addViewSupportTransformColor(toolbar)  //设置支持view变色，可以添加多个view，不指定颜色，默认和状态栏同色，还有两个重载方法
//				.titleBar(view)    //解决状态栏和布局重叠问题，任选其一
//				.statusBarView(view)  //解决状态栏和布局重叠问题，任选其一
//				.fitsSystemWindows(true)    //解决状态栏和布局重叠问题，任选其一，默认为false，当为true时一定要指定statusBarColor()，不然状态栏为透明色
//				.supportActionBar(true) //支持ActionBar使用
//				.statusBarColorTransform(R.color.orange)  //状态栏变色后的颜色
//				.navigationBarColorTransform(R.color.orange) //导航栏变色后的颜色
//				.barColorTransform(R.color.orange)  //状态栏和导航栏变色后的颜色
//				.removeSupportView(toolbar)  //移除指定view支持
//				.removeSupportAllView() //移除全部view支持
//				.addTag("tag")  //给以上设置的参数打标记
//				.getTag("tag")  //根据tag获得沉浸式参数
//				.reset()  //重置所以沉浸式参数
//				.keyboardEnable(true)  //解决软键盘与底部输入框冲突问题，默认为false
//				.setOnKeyboardListener(new OnKeyboardListener() {    //软键盘监听回调
//					@Override
//					public void onKeyboardChange(boolean isPopup, int keyboardHeight) {
//						LogUtils.e(isPopup);  //isPopup为true，软键盘弹出，为false，软键盘关闭
//					}
//				})
//				.keyboardMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE)  //单独指定软键盘模式
//				.init();  //必须调用方可沉浸式


	}

	private final ContentObserver mNavigationStatusObserver = new ContentObserver(new Handler()) {
		@Override
		public void onChange(boolean selfChange) {
			int navigationBarIsMin = Settings.System.getInt(getContentResolver(), NAVIGATIONBAR_IS_MIN, 0);
			if (navigationBarIsMin == 1) {
				//导航键隐藏了
				mImmersionBar.transparentNavigationBar().init();
			} else {
				//导航键显示了
				mImmersionBar.navigationBarColor(android.R.color.black) //隐藏前导航栏的颜色
						.fullScreen(false).init();
			}
		}
	};
}
